package com.ruoyi.procured.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.commodity.domain.ProductImage;
import com.ruoyi.commodity.mapper.ProductImageMapper;
import com.ruoyi.common.api.procured.ProcuredApi;
import com.ruoyi.common.api.procured.dto.ProcuredPlanDto;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.ProcuredOrders;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.core.domain.OrdersProduct;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.procured.domain.ProcuredProduct;
import com.ruoyi.procured.mapper.*;
import com.ruoyi.procured.service.IProcuredPlanProcessService;
import com.ruoyi.sale.domain.Plan;
import com.ruoyi.sale.domain.ShipmentsProduct;
import com.ruoyi.sale.mapper.PlanMapper;
import com.ruoyi.system.mapper.SysMenuMapper;
import com.ruoyi.template.domain.TemplateDetail;
import com.ruoyi.template.mapper.TemplateMapper;
import com.ruoyi.template.service.TemplateDetailService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.stream.Collectors;

import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.procured.domain.TbProcuredProduct;
import com.ruoyi.procured.domain.ProcuredPlan;
import com.ruoyi.procured.service.IProcuredPlanService;
import org.springframework.util.NumberUtils;

import javax.annotation.Resource;

/**
 * 采购计划Service业务层处理
 *
 * @author ruoyi
 * @date 2023-11-03
 */
@Service
public class ProcuredPlanServiceImpl implements IProcuredPlanService, ProcuredApi {
	@Autowired
	private ProcuredPlanMapper procuredPlanMapper;

	@Resource
	private ProcuredOrdersProductMapper procuredOrdersProductMapper;

	@Resource
	private ProcuredProductMapper procuredProductMapper;

	@Autowired
	private ProcuredOrdersMapper procuredOrdersMapper;

	@Autowired
	private ShipmentProductMapper shipmentProductMapper;

	@Autowired
	private PlanMapper planMapper;

	@Autowired
	private SysMenuMapper sysMenuMapper;

	@Autowired
	private TemplateMapper templateMapper;

	@Autowired
	private TemplateDetailService templateDetailService;

	@Autowired
	private IProcuredPlanProcessService procuredPlanProcessService;

	@Autowired
	private ProductImageMapper productImageMapper;

	/**
	 * 查询采购计划
	 *
	 * @param planId 采购计划主键
	 * @return 采购计划
	 */
	@Override
	public ProcuredPlan selectProcuredPlanByPlanId(Long planId) {
		ProcuredPlan procuredPlan = procuredPlanMapper.selectProcuredPlanByPlanId(planId);
		List<TbProcuredProduct> tbProcuredProductList = procuredPlan.getTbProcuredProductList();
		if (!tbProcuredProductList.isEmpty()) {
			// 提取出所有的产品id查询对应的图片
			Map<Integer, List<String>> collect = productImageMapper.selectProductImagesByProductId(tbProcuredProductList.stream().map(TbProcuredProduct::getProductId).collect(Collectors.toList()))
					.stream().collect(Collectors.groupingBy(ProductImage::getProductId, Collectors.mapping(ProductImage::getProductImagePath, Collectors.toList())));
			// 分配产品图片
			for (TbProcuredProduct tbProcuredProduct : tbProcuredProductList) {
				tbProcuredProduct.setImgName(collect.get(tbProcuredProduct.getProductId().intValue()));
			}
		}
		return procuredPlan;
	}

	/**
	 * 查询采购计划列表
	 *
	 * @param procuredPlan 采购计划
	 * @return 采购计划
	 */
	@Override
	public List<ProcuredPlan> selectProcuredPlanList(ProcuredPlan procuredPlan) {
		return procuredPlanMapper.selectProcuredPlanList(procuredPlan);
	}

	/**
	 * 新增采购计划
	 *
	 * @param procuredPlan 采购计划
	 * @return 结果
	 */
	@Transactional
	@Override
	public int insertProcuredPlan(ProcuredPlan procuredPlan, Long userId, String componentPath) {

		//获取菜单ID
		SysMenu sysMenu = sysMenuMapper.selectMenuByComponent(componentPath);
		if (sysMenu == null) {
			throw new ServiceException("获取菜单ID失败，请刷新页面重新操作。");
		}

		//校验当前菜单和用户是否绑定
		String templateId = templateMapper.findTemplateIdByUserIdAndMenuId(userId, sysMenu.getMenuId());
		if (StringUtils.isNull(templateId)) {
			throw new ServiceException("未匹配到对应的审核模板，请联系人事匹配后再操作。");
		}

		//获取模板详情
		List<TemplateDetail> templateDetails = templateDetailService.getTemplateDetailList(templateId);
		if (templateDetails.isEmpty()) {
			throw new ServiceException("获取模板详情失败。");
		}
		TemplateDetail firstDetail = templateDetails.get(0);
		Long reviewerUserId = Long.valueOf(firstDetail.getReviewerId());

		procuredPlan.setAddTime(new Date());
		procuredPlan.setPlanNumber(generateCodePlan());
		procuredPlan.setActualAmount(BigDecimal.ZERO);
		procuredPlan.setReviewerUserId(reviewerUserId);
		Long total = procuredPlan.getTbProcuredProductList()
				.stream()
				.mapToLong(TbProcuredProduct::getNumber)  // 替换 getPrice() 为你需要累加的属性方法
				.sum();
		procuredPlan.setTotal(total); // 总件数

		// 验证销售计划是否已经存在于其他采购计划
//		int result = procuredPlanMapper.selectBySalePlanNumberCount(procuredPlan.getSalesPlanNumber());
//		if (result > 0) {
//			throw new ServiceException("销售计划已被其他采购计划选择，请刷新页面重试！");
//		}
		int rows = procuredPlanMapper.insertProcuredPlan(procuredPlan);
		// 插入采购商品明细
		insertTbProcuredProduct(procuredPlan, true);
//		List<TbProcuredProduct> procuredProducts = procuredPlanMapper.selectProcuredProductById(procuredPlan.getPlanId());
//		BigDecimal totalMoney = BigDecimal.ZERO; // 初始化总钱数为0
//		Long total = 0L;
//		for (TbProcuredProduct procuredProduct : procuredProducts) {
//			BigDecimal taxIncluded = procuredProduct.getTaxIncluded();
//			Long number = procuredProduct.getNumber();
//			totalMoney = totalMoney.add(taxIncluded); // 将单个金额加入到总钱数中
//			total += number;
//		}
//		ProcuredPlan newProcuredPlan = new ProcuredPlan();
//		newProcuredPlan.setPlanId(procuredPlan.getPlanId());
//		newProcuredPlan.setTotalAmount(totalMoney);
//		newProcuredPlan.setTotal(total);
//		procuredPlanMapper.updateProcuredPlan(newProcuredPlan);

		//更新销售计划明细表（tb_shipments_product）selectStatus :0（未选），1（已选）
		updateShipmentsProductSelectStatus(procuredPlan, procuredPlan.getSalesPlanId());
		//更新销售计划状态（判断是否全部已加入采购计划）
		updatePlanStatusByPlanId(procuredPlan.getSalesPlanId(), procuredPlan);

		//审核表插入审核流程记录
		procuredPlanProcessService.insertProcuredPlanProcessQuash((procuredPlan.getPlanId()).toString(), templateDetails, userId);
		return rows;
	}


	/**
	 * 生成随机数
	 *
	 * @return
	 */
	public String generateCodePlan() {
		// 获取当前日期
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
		String currentDate = dateFormat.format(new Date());
		// 获取序列号
		String planNumber = procuredPlanMapper.selectProcuredPlanNumber();
		String randomNumber;
		// ...根据自己的业务逻辑实现获取序列号的方法
		if (StringUtils.isEmpty(planNumber)) {
			randomNumber = Constants.RANDOM_NUMBERS;
		} else {
			randomNumber = String.format("%04d", (NumberUtils.parseNumber(planNumber.substring(10), Long.class) + 1));
		}
		// 拼接生成的代码
		String code = Constants.CODE_PLAN + currentDate + randomNumber;

		return code;
	}


//	@Transactional
//	@Override
//	public int updateProcuredPlan(ProcuredPlan procuredPlan) {
//		// 判断采购计划状态是否被核准了
//		if (!procuredPlan.getPlanStatus().equals("0")) {
//			throw new ServiceException("数据发生变化，请刷新页面重试!");
//		}
//		procuredPlan.setUpdateTime(DateUtils.getNowDate());
//		procuredPlanMapper.deleteTbProcuredProductByPlanId(procuredPlan.getPlanId());
//		insertTbProcuredProduct(procuredPlan, false);
//		List<TbProcuredProduct> procuredProducts = procuredPlanMapper.selectProcuredProductById(procuredPlan.getPlanId());
//
//		List<Long> longList = new ArrayList<>();
//
////		BigDecimal totalMoney = BigDecimal.ZERO; // 初始化总钱数为0
////		Long total = 0L;
//		for (TbProcuredProduct procuredProduct : procuredProducts) {
////			BigDecimal taxIncluded = procuredProduct.getTaxIncluded();
////			Long number = procuredProduct.getNumber();
////			totalMoney = totalMoney.add(taxIncluded); // 将单个金额加入到总钱数中
////			total += number;
//			longList.add(procuredProduct.getProductId());
//		}
////		procuredPlan.setTotal(total);
////		procuredPlan.setTotalAmount(totalMoney);
//
//		//比较采购计划商品的差异，新增还是删除
//		compareProducts(procuredPlan, longList);
//
//		return procuredPlanMapper.updateProcuredPlan(procuredPlan);
//	}

	/**
	 * 修改采购计划
	 *
	 * @param procuredPlan 采购计划
	 * @return 结果
	 */
	@Transactional
	@Override
	public int updateProcuredPlan(ProcuredPlan procuredPlan) {
		// 校验采购计划状态，只有状态为“0”（未核准）的才能修改
		if (!"0".equals(procuredPlan.getPlanStatus())) {
			throw new ServiceException("数据发生变化，请刷新页面重试!");
		}
		procuredPlan.setUpdateTime(DateUtils.getNowDate());

		// 删除原有采购计划中的所有采购商品明细
		procuredPlanMapper.deleteTbProcuredProductByPlanId(procuredPlan.getPlanId());

		// 重新插入新的采购商品明细（第二个参数标识是否新增采购计划时的特殊处理，此处为false）
		insertTbProcuredProduct(procuredPlan, false);

		// 查询更新后的采购商品明细，并更新到procuredPlan中
		List<TbProcuredProduct> procuredProducts = procuredPlanMapper.selectProcuredProductById(procuredPlan.getPlanId());
		procuredPlan.setTbProcuredProductList(procuredProducts);

		// 计算本采购计划中所有产品的总件数（也可以同步更新总金额等）
		Long total = procuredProducts.stream().mapToLong(TbProcuredProduct::getNumber).sum();
		procuredPlan.setTotal(total);

		// 更新对应销售计划中各产品的选中状态
		// 此方法内部会根据当前采购计划中各产品的数量，加上其他已存在的采购计划的数量进行汇总，
		// 与销售计划中产品的计划数量比较，若已完全选完，则将销售计划明细置为已选（selectStatus=1）
		updateShipmentsProductSelectStatus(procuredPlan, procuredPlan.getSalesPlanId());

		// 更新销售计划整体的状态（判断是否所有产品都已经完全加入采购计划）
		updatePlanStatusByPlanId(procuredPlan.getSalesPlanId(), procuredPlan);

		// 最后更新采购计划主表
		return procuredPlanMapper.updateProcuredPlan(procuredPlan);
	}

	/**
	 * 批量删除采购计划
	 *
	 * @param planIds 需要删除的采购计划主键
	 * @return 结果
	 */
	@Transactional
	@Override
	public int deleteProcuredPlanByPlanIds(Long[] planIds) {

		// 查询所有要删除的采购计划状态
		List<ProcuredPlan> procuredPlans = procuredPlanMapper.selectProcuredPlanByplanIds(planIds);
		// 判断本次删除的采购计划是否都是未核准的采购计划
		boolean result = procuredPlans.stream().anyMatch(item -> !item.getPlanStatus().equals("0"));

		if (result) {
			throw new ServiceException("数据发生变化，请刷新页面重试!");
		}

		// 先删除采购计划对应的采购产品明细
		procuredPlanMapper.deleteTbProcuredProductByPlanIds(planIds);
		// 删除采购计划主表数据
		int rows = procuredPlanMapper.deleteProcuredPlanByPlanIds(planIds);

		// 根据每个采购计划对应的销售计划，重新汇总更新销售计划明细的选中状态以及整体销售计划状态
		// 为避免重复更新同一销售计划，可先取出销售计划编号的集合
		Set<String> salesPlanNumbers = procuredPlans.stream()
				.map(ProcuredPlan::getSalesPlanNumber)
				.collect(Collectors.toSet());

		for (String salesPlanNumber : salesPlanNumbers) {
			updatePlanAndShipmentsProductSelectStatus(salesPlanNumber);
		}
		return rows;
	}

	/**
	 * 删除采购计划信息
	 *
	 * @param planId 采购计划主键
	 * @return 结果
	 */
	@Transactional
	@Override
	public int deleteProcuredPlanByPlanId(Long planId) {
		// 1. 删除当前采购计划对应的采购产品明细
		procuredPlanMapper.deleteTbProcuredProductByPlanId(planId);

		// 2. 查询当前采购计划信息，获取销售计划编号
		ProcuredPlan procuredPlan = procuredPlanMapper.selectById(planId);
		if (procuredPlan == null) {
			throw new ServiceException("采购计划不存在！");
		}

		// 3. 根据销售计划编号查询销售计划信息
		LambdaQueryWrapper<Plan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(Plan::getPlanNumber, procuredPlan.getSalesPlanNumber());
		Plan plan = planMapper.selectOne(queryWrapper);
		if (plan == null || plan.getId() == null) {
			throw new ServiceException("销售计划不存在，请联系管理员！");
		}

		// 4. 删除当前采购计划主记录
		int rows = procuredPlanMapper.deleteProcuredPlanByPlanId(planId);

		// 5. 重新汇总该销售计划下所有剩余采购计划中的采购产品数据
		List<TbProcuredProduct> aggregatedProducts = procuredPlanMapper.selectProcuredProductsBySalesPlanId(plan.getId());
		ProcuredPlan aggregatedProcuredPlan = new ProcuredPlan();
		aggregatedProcuredPlan.setSalesPlanId(plan.getId());
		aggregatedProcuredPlan.setTbProcuredProductList(aggregatedProducts);

		// 6. 根据汇总后的数据更新销售计划明细的选中状态
		updateShipmentsProductSelectStatus(aggregatedProcuredPlan, plan.getId());
		// 7. 更新销售计划整体状态（判断所有产品是否已全部选完）
		updatePlanStatusByPlanId(plan.getId(), aggregatedProcuredPlan);

		return rows;
	}


	@Override
	public int updateProcuredPlanStatus(Long[] planIds, boolean flay, String approver) {
		if (flay) {
			return procuredPlanMapper.updateProcuredPlanStatus(planIds, "1", approver);
		}
		return procuredPlanMapper.updateProcuredPlanStatus(planIds, "0", approver);
	}


	//	public List<TbProcuredProduct> selectTbProcuredProductList(TbProcuredProduct tbProcuredProduct) {
//		return procuredPlanMapper.selectTbProcuredProductList(tbProcuredProduct);
//	}
	@Override
	public List<TbProcuredProduct> selectTbProcuredProductList(TbProcuredProduct tbProcuredProduct) {
		// 1. 查询所有产品数据
		List<TbProcuredProduct> productList = procuredPlanMapper.selectTbProcuredProductList(tbProcuredProduct);

		// 若产品列表为空，则直接返回
		if (productList == null || productList.isEmpty()) {
			return productList;
		}

		// 2. 获取所有产品的 productId 列表
		List<Long> productIds = productList.stream()
				.map(TbProcuredProduct::getProductId)
				.collect(Collectors.toList());

		// 3. 查询产品图片并按照 product_id 分组，key 为 Integer，value 为图片路径列表
		Map<Integer, List<String>> imageMap = productImageMapper.selectProductImagesByProductId(productIds)
				.stream()
				.collect(Collectors.groupingBy(
						ProductImage::getProductId,
						Collectors.mapping(ProductImage::getProductImagePath, Collectors.toList())
				));

		// 4. 将图片路径分配到对应的产品中
		for (TbProcuredProduct product : productList) {
			Integer key = product.getProductId().intValue();
			List<String> images = imageMap.get(key);
			product.setImgName(images);
		}

		return productList;
	}

	@Override
	public List<TbProcuredProduct> selectTbProcuredProductListById(Long[] ids) {
		return procuredPlanMapper.selectTbProcuredProductListById(ids);
	}

	@Override
	public int updateProcuredProductSelectedStatus(Long[] ids, boolean flay) {
		String selectedStatus;
		if (flay) {
			selectedStatus = "1";
			return procuredPlanMapper.updateProcuredProductSelectedStatus(ids, selectedStatus);
		} else {
			selectedStatus = "0";
			return procuredPlanMapper.updateProcuredProductSelectedStatus(ids, selectedStatus);
		}
	}

	/**
	 * 生成批次号
	 *
	 * @return 新生成的批次号
	 */
	public synchronized String generateBatchNumber() {
		// 获取当前日期（格式：yyMMdd）
		Date now = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd");
		String currentDate = dateFormat.format(now);

		// 查询当天最新批次号
		String latestBatchNumber = procuredOrdersMapper.getLatestBatchNumber(currentDate);

		// 定义新的批次号
		String newBatchNumber;

		if (latestBatchNumber == null || !latestBatchNumber.startsWith(currentDate)) {
			// 如果当天没有批次号，从 01 开始
			newBatchNumber = currentDate + "01";
		} else {
			// 提取当天最新批次号的最后两位（递增编号）
			String lastSequenceStr = latestBatchNumber.substring(6); // 批次号的最后两位
			int lastSequence = Integer.parseInt(lastSequenceStr); // 转为整数

			// 检查是否超出最大值
			if (lastSequence >= 99) {
				throw new IllegalArgumentException("流水号已达最大值，无法生成新的批次号！");
			}

			// 序号递增
			int newSequence = lastSequence + 1;
			// 格式化为两位（不足两位补零）
			String newSequenceStr = String.format("%02d", newSequence);

			// 拼接新的批次号
			newBatchNumber = currentDate + newSequenceStr;
		}

		return newBatchNumber;
	}


//	@Transactional
//	@Override
//	public int insertProcuredOrders(ProcuredPlan procuredPlan, String nickname) {
//		ProcuredOrders procuredOrders = new ProcuredOrders();
//		procuredOrders.setOrdersNumber(generateCode());
//		procuredOrders.setPlanId(procuredPlan.getPlanId());
//		procuredOrders.setAddTime(new Date());
//		procuredOrders.setCurrency(procuredPlan.getCurrency());
//		procuredOrders.setFreight(procuredPlan.getFreight());
//		procuredOrders.setDiscountAmount(procuredPlan.getDiscountAmount());
//		procuredOrders.setPurchaseBatchNumber(generateBatchNumber());
//		procuredOrders.setRemark(procuredPlan.getPurchaseOrderRemark());
//		List<TbProcuredProduct> tbProcuredProductList = procuredPlan.getBatchOrderProductList();
//		List<OrdersProduct> ordersProductList = procuredOrders.getOrdersProductList();
//		List<OrdersProduct> copiedList = tbProcuredProductList.stream()
//				.map(tbProcuredProduct -> {
//					// TODO: 将TbProcuredProduct的属性拷贝到OrdersProduct
//					OrdersProduct ordersProduct = new OrdersProduct();
//					ordersProduct.setProNo(tbProcuredProduct.getProNo());
//					ordersProduct.setProductName(tbProcuredProduct.getProductName());
//					ordersProduct.setProductPrice(tbProcuredProduct.getProductPrice());
//					ordersProduct.setTransferableNumber(tbProcuredProduct.getTransferableNumber());
//					ordersProduct.setNotStockedNumber(tbProcuredProduct.getTransferableNumber());
//					ordersProduct.setProductRemark(tbProcuredProduct.getProductRemark());
//					ordersProduct.setProductId(tbProcuredProduct.getProductId());
//					ordersProduct.setWaitingStock(tbProcuredProduct.getTransferableNumber());
//					ordersProduct.setUnnotifiedQuantity(tbProcuredProduct.getTransferableNumber());
//					ordersProduct.setNotifiedCount(Constants.INITIALIZE);
//					ordersProduct.setNotificationQuantity(Constants.INITIALIZE);
//					return ordersProduct;
//				})
//				.collect(Collectors.toList());
//		// 将拷贝后的列表赋值给ordersProductList
//		if (ordersProductList == null) {
//			ordersProductList = new ArrayList<>();
//		}
//		if(true){
//			throw new ServiceException("报错了");
//		}
//		ordersProductList.addAll(copiedList);
//		Long total = 0L;
//		BigDecimal originalAmount = BigDecimal.ZERO; // 初始化原始金额为0
//		BigDecimal payableAmount = BigDecimal.ZERO; //初始化应付金额为0
//		for (OrdersProduct ordersProduct : ordersProductList) {
//			total = total + ordersProduct.getTransferableNumber();
//			//计算原始金额 = 产品单价 * 汇率 * 商品数量
//			originalAmount = originalAmount.add(ordersProduct.getProductPrice().multiply(BigDecimal.valueOf(ordersProduct.getTransferableNumber())).multiply(procuredPlan.getCurrency()));
//		}
//
////		if(true){
////			throw new ServiceException("报错了");
////		}
//		BigDecimal totalTax = tbProcuredProductList.stream()
//				.map(product -> {
//					BigDecimal rate = new BigDecimal(product.getRate());  // 将税率的 String 类型转换为 BigDecimal
//					return product.getProductPrice()   // 单价
//							.multiply(BigDecimal.valueOf(product.getTransferableNumber()))  // 乘以数量
//							.multiply(rate.divide(BigDecimal.valueOf(100)))  // 乘以税率
//							.multiply(procuredPlan.getCurrency());
//				})
//				.reduce(BigDecimal.ZERO, BigDecimal::add)  // 累加税额
//				.setScale(2, RoundingMode.HALF_UP);  // 最终结果保留两位小数并四舍五入
//
//
//		BigDecimal shippingFee = procuredPlan.getFreight();//运费
//		//如果没有勾选运费为供应商付款的话就是自己付款，那么运费就不要算在应付金额里面去了
//		if (procuredPlan.getFlag()) {
//			shippingFee = BigDecimal.ZERO;
//		}
//		//计算应付金额=（ 产品单价 * 汇率 * 商品数量 + 税额（ 税率 * 汇率 * 产品单价 * 产品数量 ） + 运费
//		payableAmount = (originalAmount.add(totalTax).add(shippingFee)).setScale(2, RoundingMode.HALF_UP);
//		procuredOrders.setTotal(total);
//		procuredOrders.setApprover(nickname);
//		procuredOrders.setApprovedTime(DateUtils.getNowDate());
//		procuredOrders.setIsSupplierPaysFreight(procuredPlan.getFlag() ? 0 : 1);
//		procuredOrders.setAmountDue(payableAmount);
//		procuredOrders.setOriginalAmount(originalAmount);
//		procuredOrders.setOrdersProductList(ordersProductList);
//
//		//插入采购订单
//		int rows = procuredOrdersMapper.insertProcuredOrders(procuredOrders);
//
//		//插入订单商品详细
//		insertOrdersProduct(procuredOrders, procuredPlan);
//
//		//修改采购商品表的已转数量和可转数量
//		updateProcuredProductNumber(tbProcuredProductList);
//
//		//修改采购计划下单状态和采购计划的实际金额
//		updateProcuredPlanStatusByVersion(procuredPlan.getPlanId(), payableAmount, procuredPlan.getVersion());
//		return rows;
//	}


	/**
	 * 分批下单
	 *
	 * @param procuredPlan
	 * @param nickname
	 * @return
	 */
	@Transactional
	@Override
	public int insertProcuredOrders(ProcuredPlan procuredPlan, String nickname) {
		// 判断采购计划状态是否被核准了
		if (procuredPlan.getPlanStatus().equals("0") || procuredPlan.getPlanStatus().equals("3")) {
			throw new ServiceException("数据发生变化，请刷新页面重试!");
		}
		if(procuredPlan.getBatchOrderProductList().isEmpty()){
			throw new ServiceException("下单的产品为空，请检查!");
		}
		// 从采购计划中获取所有产品列表
		List<TbProcuredProduct> tbProcuredProductList = procuredPlan.getBatchOrderProductList();
		// 按 vendorId 分组，key 为供应商ID，value 为对应的产品列表
		Map<Integer, List<TbProcuredProduct>> groupByVendor = tbProcuredProductList.stream()
				.collect(Collectors.groupingBy(TbProcuredProduct::getVendorId));

		// 初始化所有插入的采购订单数量
		int totalInsertedOrders = 0;
		// 初始化所有订单的应付金额，用于更新采购计划的实际金额
		BigDecimal overallPayableAmount = BigDecimal.ZERO;

		// 遍历每个供应商分组，分别生成采购订单
		for (Map.Entry<Integer, List<TbProcuredProduct>> entry : groupByVendor.entrySet()) {
			// 获取当前分组的供应商ID
			Integer vendorId = entry.getKey();
			// 获取当前供应商对应的产品列表
			List<TbProcuredProduct> productGroup = entry.getValue();

			// 创建新的采购订单对象
			ProcuredOrders procuredOrders = new ProcuredOrders();
			// 生成并设置订单编号
			procuredOrders.setOrdersNumber(generateCode(1).get(0));
			// 设置1688订单号
			procuredOrders.setOrderNo1688(productGroup.get(0).getOrderNo1688()); // 取分组中任意产品的1688订单号，因为供应商一样的产品这个1688订单号都是一样的
			// 设置关联的采购计划ID
			procuredOrders.setPlanId(procuredPlan.getPlanId());
			// 设置订单创建时间
			procuredOrders.setAddTime(new Date());
			// 设置订单供应商
			procuredOrders.setVendorId(vendorId);
			// 设置订单运费
			// 累加所有产品的运费，并对结果进行保留两位小数的逢尾数进一处理
			BigDecimal totalFreight = productGroup.stream()
					.map(product -> product.getFreight() == null ? BigDecimal.ZERO : product.getFreight())
					.reduce(BigDecimal.ZERO, BigDecimal::add)
					.setScale(4, RoundingMode.CEILING);
			procuredOrders.setFreight(totalFreight);
			// 设置优惠金额
//			procuredOrders.setDiscountAmount(procuredPlan.getDiscountAmount());
			// 生成并设置采购批次号
			procuredOrders.setPurchaseBatchNumber(generateBatchNumber());
			// 设置订单备注
			procuredOrders.setRemark(procuredPlan.getPurchaseOrderRemark());
			// 如果订单实体中有供应商ID字段，可在此处设置：procuredOrders.setVendorId(vendorId);

			// 创建订单产品列表，用于存储当前供应商的所有产品
			List<OrdersProduct> ordersProductList = new ArrayList<>();
			// 初始化订单中产品的总数量
			Long total = 0L;
			// 初始化订单原始金额（单价 * 数量 * 汇率）
			BigDecimal originalAmount = BigDecimal.ZERO;

			// 遍历当前供应商组内的所有产品，构建订单产品对象
			for (TbProcuredProduct tbProcuredProduct : productGroup) {
				// 创建订单产品对象
				OrdersProduct ordersProduct = new OrdersProduct();
				// 拷贝产品编号
				ordersProduct.setProNo(tbProcuredProduct.getProNo());
				// 拷贝产品名称
				ordersProduct.setProductName(tbProcuredProduct.getProductName());
				// 拷贝产品单价
				ordersProduct.setProductPrice(tbProcuredProduct.getProductPrice());
				// 拷贝可转移数量
				ordersProduct.setTransferableNumber(tbProcuredProduct.getTransferableNumber());
				// 初始未入库数量设为可转移数量
				ordersProduct.setNotStockedNumber(tbProcuredProduct.getTransferableNumber());
				// 拷贝产品备注
				ordersProduct.setProductRemark(tbProcuredProduct.getProductRemark());
				// 拷贝产品ID
				ordersProduct.setProductId(tbProcuredProduct.getProductId());
				// 设置待入库数量
				ordersProduct.setWaitingStock(tbProcuredProduct.getTransferableNumber());
				// 设置未通知数量
				ordersProduct.setUnnotifiedQuantity(tbProcuredProduct.getTransferableNumber());
				// 初始化已通知数量为常量初始值
				ordersProduct.setNotifiedCount(Constants.INITIALIZE);
				// 初始化通知数量为常量初始值
				ordersProduct.setNotificationQuantity(Constants.INITIALIZE);
				// 供应商ID
				ordersProduct.setVendorId(tbProcuredProduct.getVendorId());
				// 交付时间
				ordersProduct.setDeliveryTime(tbProcuredProduct.getDeliveryTime());
				// 货币单位
				ordersProduct.setMonetaryId(tbProcuredProduct.getMonetaryId());
				// 汇率
				ordersProduct.setCurrency(tbProcuredProduct.getCurrency());
				// 运费
//				ordersProduct.setFreight(tbProcuredProduct.getFlag() != null ? BigDecimal.ZERO : tbProcuredProduct.getFreight());
				// 运费是否由供应商付
				ordersProduct.setFlag(Boolean.TRUE.equals(tbProcuredProduct.getFlag()));
				// 税率
				ordersProduct.setRate(tbProcuredProduct.getRate());
				// 税额
				ordersProduct.setTax(tbProcuredProduct.getTax());
				// 含税金额
				ordersProduct.setTaxIncluded(tbProcuredProduct.getTaxIncluded());
				// 1688订单号
				ordersProduct.setOrderNo1688(tbProcuredProduct.getOrderNo1688());
				// GTIN
				ordersProduct.setGtin(tbProcuredProduct.getGtin());
				// 将构建的订单产品添加到订单产品列表中
				ordersProductList.add(ordersProduct);

				// 累加当前产品的数量到订单总数量
				total += tbProcuredProduct.getTransferableNumber();
				// 计算并累加原始金额：单价 * 数量 * 汇率
				originalAmount = originalAmount.add(
						tbProcuredProduct.getProductPrice()
								.multiply(BigDecimal.valueOf(tbProcuredProduct.getTransferableNumber()))
								.multiply(tbProcuredProduct.getCurrency())
				);
			}

			// 计算当前供应商组内所有产品的总税额
//			BigDecimal totalTax = productGroup.stream()
//					.map(product -> {
//						// 将税率从字符串转换为 BigDecimal
//						BigDecimal rate = new BigDecimal(product.getRate());
//						// 计算单个产品税额：单价 * 数量 * (税率/100) * 汇率
//						return product.getProductPrice()
//								.multiply(BigDecimal.valueOf(product.getTransferableNumber()))
//								.multiply(rate.divide(BigDecimal.valueOf(100)))
//								.multiply(product.getCurrency());
//					})
//					// 累加所有产品的税额
//					.reduce(BigDecimal.ZERO, BigDecimal::add)
//					// 保留两位小数，采用四舍五入模式
//					.setScale(2, RoundingMode.HALF_UP);

			// 计算当前订单的应付金额 = 所有对应分组产品中的含税金额汇总
			BigDecimal payableAmount = productGroup.stream()
					.map(TbProcuredProduct::getTaxIncluded) // 获取每个产品的含税金额
					.filter(Objects::nonNull) // 过滤掉任何为 null 的值
					.reduce(BigDecimal.ZERO, BigDecimal::add); // 将所有含税金额求和，初始值为 BigDecimal.ZERO


			// 设置订单中产品总数量
			procuredOrders.setTotal(total);
			// 设置下单人为传入的 nickname
			procuredOrders.setApprover(nickname);
			// 设置下单时间为当前时间
			procuredOrders.setApprovedTime(DateUtils.getNowDate());
			// 设置运费支付方式（1 表示自付，0 表示供应商支付）
			// procuredOrders.setIsSupplierPaysFreight(procuredPlan.getFlag() ? 1 : 0);
			// 设置订单应付金额
			procuredOrders.setAmountDue(payableAmount.add(procuredOrders.getFreight()));
			// 设置订单原始金额
			procuredOrders.setOriginalAmount(originalAmount);
			// 设置当前订单的产品列表
			procuredOrders.setOrdersProductList(ordersProductList);

			// 插入当前供应商对应的采购订单到数据库
			int rows = procuredOrdersMapper.insertProcuredOrders(procuredOrders);
			// 累加成功插入的订单数量
			totalInsertedOrders += rows;

			// 插入订单中的详细商品记录
			insertOrdersProduct(procuredOrders, procuredPlan);

			// 累加当前订单的应付金额，用于后续更新采购计划的实际金额
			overallPayableAmount = overallPayableAmount.add(procuredOrders.getAmountDue());
		}

		// 更新所有采购商品的已转数量和可转数量
		updateProcuredProductNumber(tbProcuredProductList);
		// 更新采购计划的下单状态和实际金额，传入采购计划ID、总应付金额以及版本号（用于乐观锁）
		updateProcuredPlanStatusByVersion(procuredPlan.getPlanId(), overallPayableAmount, procuredPlan.getVersion());
//
//		if(true){
//			throw new ServiceException("");
//		}
		// 返回总共插入的采购订单数量
		return totalInsertedOrders;
	}


	@Override
	public int deleteProcuredOrdersByOrdersNumber(String[] ordersNumbers) {
		procuredOrdersMapper.deleteOrdersProductByOrdersNumber(ordersNumbers);
		return procuredOrdersMapper.deleteProcuredOrdersByOrdersNumber(ordersNumbers);
	}

	@Override
	public int updateProcuredPlanOrdersNumber(String[] ordersNumbers, boolean flay) {
		procuredPlanMapper.updateProcuredProductByTurnedNumber(ordersNumbers);
		if (flay) {
			return procuredPlanMapper.updateProcuredPlanOrdersNumber(ordersNumbers, Constants.STATUS_ONE);
		} else {
			return procuredPlanMapper.updateProcuredPlanOrdersNumber(ordersNumbers, Constants.STATUS_TOW);
		}
	}


	/**
	 * 根据采购计划详情查询采购订单信息
	 *
	 * @param procuredOrder 包含采购计划ID的查询条件
	 * @return 采购订单列表，包含订单商品和产品图片
	 */
	@Override
	public List<ProcuredOrders> selectProcuredPlanByDetails(ProcuredOrders procuredOrder) {
		// 参数校验
		if (procuredOrder == null || procuredOrder.getPlanId() == null) {
			return Collections.emptyList();
		}

		// 根据采购计划id查询所有的采购订单
		List<ProcuredOrders> ordersList = procuredOrdersMapper.selectByPlanId(procuredOrder);

		// 如果没有订单，返回空列表
		if (ordersList.isEmpty()) {
			return Collections.emptyList();
		}

		// 收集所有采购订单的订单ID
		List<Long> ordersIds = ordersList.stream()
				.map(ProcuredOrders::getOrdersId)
				.collect(Collectors.toList());

		// 查询所有订单商品
		List<OrdersProduct> result = procuredOrdersProductMapper.selectByOrdersId(ordersIds, procuredOrder.getPlanId());
		List<OrdersProduct> ordersProducts = mergeOrdersProducts(result); // 合并同一个SKU不同GTIN的数据

		// 如果没有订单商品，直接返回订单列表
		if (ordersProducts.isEmpty()) {
			return ordersList;
		}

		// 收集所有产品ID
		List<Long> productIds = ordersProducts.stream()
				.map(OrdersProduct::getProductId)
				.filter(Objects::nonNull)
				.collect(Collectors.toList());

		// 只在有产品ID时查询产品图片
		Map<Integer, List<String>> productImageMap = Collections.emptyMap();
		if (!productIds.isEmpty()) {
			// 查询产品图片并按产品ID分组
			productImageMap = productImageMapper.selectProductImagesByProductId(productIds)
					.stream()
					.collect(Collectors.groupingBy(
							ProductImage::getProductId,
							Collectors.mapping(ProductImage::getProductImagePath, Collectors.toList())
					));
		}

		// 分配产品图片到订单商品
		final Map<Integer, List<String>> finalProductImageMap = productImageMap;
		ordersProducts.forEach(item -> {
			Integer productId = item.getProductId() != null ? item.getProductId().intValue() : null;
			if (productId != null) {
				item.setImagePath(finalProductImageMap.getOrDefault(productId, Collections.emptyList()));
			}
		});

		// 按订单ID分组订单商品
		Map<Long, List<OrdersProduct>> ordersProductMap = ordersProducts.stream()
				.collect(Collectors.groupingBy(OrdersProduct::getOrdersId));

		// 为每个采购订单设置对应的商品列表
		ordersList.forEach(order -> {
			Long ordersId = order.getOrdersId();
			order.setOrdersProductList(ordersProductMap.getOrDefault(ordersId, Collections.emptyList()));
		});

		return ordersList;
	}

	public List<OrdersProduct> mergeOrdersProducts(List<OrdersProduct> rawList) {
		// 保持插入顺序，用 LinkedHashMap
		Map<String, OrdersProduct> map = new LinkedHashMap<>();

		for (OrdersProduct op : rawList) {
			// 生成分组 Key
			String key = op.getOrdersId() + "_" + op.getProductId();

			if (!map.containsKey(key)) {
				// 第一次见到，clone 一个新对象
				OrdersProduct agg = new OrdersProduct();
				BeanUtils.copyProperties(op, agg);

				// 初始化 gtins 列表
				agg.setGtins(new ArrayList<>());
				agg.getGtins().add(op.getGtin());

				// 后续累加字段已经在 agg 里有了初始值
				map.put(key, agg);
			} else {
				// 已有聚合对象，做累加
				OrdersProduct agg = map.get(key);

				// 累加数值字段
				agg.setTransferableNumber(
						agg.getTransferableNumber() + op.getTransferableNumber()
				);
				agg.setFreight(
						agg.getFreight().add(op.getFreight())
				);
				agg.setAmount(
						agg.getAmount().add(op.getAmount())
				);
				agg.setTotalCost(
						agg.getTotalCost().add(op.getTotalCost())
				);
				agg.setStorageNumber(
						agg.getStorageNumber() + op.getStorageNumber()
				);

				// 收集 gtin
				agg.getGtins().add(op.getGtin());
			}
		}

		// 返回聚合结果
		return new ArrayList<>(map.values());
	}

	/**
	 * 新增采购订单商品信息
	 *
	 * @param procuredOrders 采购订单对象
	 */
	public void insertOrdersProduct(ProcuredOrders procuredOrders, ProcuredPlan procuredPlan) {
		List<OrdersProduct> ordersProductList = procuredOrders.getOrdersProductList();
		Long ordersId = procuredOrders.getOrdersId();

		if (ordersProductList != null) {
			List<OrdersProduct> list = new ArrayList<>();

			//拿到总商品数量
			long sum = ordersProductList.stream().mapToLong(OrdersProduct::getTransferableNumber).sum();

			// 遍历每个订单产品，并计算金额
			for (OrdersProduct ordersProduct : ordersProductList) {
				// 如果删除状态为空，设置默认值
				if (ordersProduct.getDeleteStatus() == null) {
					ordersProduct.setDeleteStatus(Constants.SUCCESS);
				}

				// 计算产品金额 = (产品价格 * 可转数量 * 汇率) + 税额
				BigDecimal productAmount = ordersProduct.getProductPrice()
						.multiply(BigDecimal.valueOf(ordersProduct.getTransferableNumber()))  // 产品价格 * 可转数量
						.multiply(ordersProduct.getCurrency())  // 乘以汇率
						.setScale(4, RoundingMode.HALF_UP);  // 保留两位小数，四舍五入

				// 税率要除以 100 以转换为小数形式，例如 10% -> 0.10
				BigDecimal taxRate = new BigDecimal(ordersProduct.getRate()).divide(BigDecimal.valueOf(100));

				// 计算税额 = 产品金额 * 税率
				BigDecimal taxAmount = productAmount.multiply(taxRate).setScale(4, RoundingMode.HALF_UP);

				// 计算总金额 = 产品金额 + 税额
				BigDecimal totalAmount = productAmount.add(taxAmount).setScale(4, RoundingMode.HALF_UP);

				//计算总成本
				BigDecimal transferableNumber = BigDecimal.valueOf(ordersProduct.getTransferableNumber());
				BigDecimal totalSum = BigDecimal.valueOf(sum);

				BigDecimal avg = transferableNumber.divide(totalSum, 6, RoundingMode.HALF_UP); // 保留4位小数，四舍五入

				BigDecimal freight = BigDecimal.ZERO;
				if (ordersProduct.getFlag() == null || !ordersProduct.getFlag()) { // 等于空说明不是供应商付
					// 订单总运费
					freight = procuredOrders.getFreight();
				}
				BigDecimal totalCost = totalAmount.add(freight.multiply(avg));//计算总成本=总金额+当前商品所占运费
				ordersProduct.setFreight(freight.multiply(avg));
				ordersProduct.setStorageNumber(0L);   //设置初始入库值
				ordersProduct.setTotalCost(totalCost);  //设置总成本
				ordersProduct.setAmount(totalAmount);  // 设置最终金额
				ordersProduct.setOrdersId(ordersId);  // 设置订单ID
				ordersProduct.setCreateTime(new Date());
				ordersProduct.setUpdateTime(new Date());

				// 将处理好的 OrdersProduct 添加到列表中
				list.add(ordersProduct);
			}

			// 批量插入订单产品
			if (!list.isEmpty()) {
				procuredOrdersMapper.batchOrdersProduct(list);
			}
		}
	}

	/**
	 * 新增${subTable.functionName}信息
	 *
	 * @param procuredPlan 采购计划对象
	 */
	public void insertTbProcuredProduct(ProcuredPlan procuredPlan, boolean flay) {
		List<TbProcuredProduct> tbProcuredProductList = procuredPlan.getTbProcuredProductList();
		Long planId = procuredPlan.getPlanId();
		if (StringUtils.isNotNull(tbProcuredProductList)) {
			List<TbProcuredProduct> list = new ArrayList<TbProcuredProduct>();
			for (TbProcuredProduct tbProcuredProduct : tbProcuredProductList) {
				if (flay) {
					tbProcuredProduct.setSelectedStatus("0");
				}
				tbProcuredProduct.setTransferableNumber(tbProcuredProduct.getNumber() - tbProcuredProduct.getTurnedNumber());
				tbProcuredProduct.setCreateTime(new Date());
				tbProcuredProduct.setCreateBy(SecurityUtils.getNickname());
				tbProcuredProduct.setPlanId(planId);
				tbProcuredProduct.setOriginalPurchaseQuantity(tbProcuredProduct.getNumber().intValue());
				list.add(tbProcuredProduct);
			}
			if (list.size() > 0) {
				procuredPlanMapper.batchTbProcuredProduct(list);
			}
		}
	}

	/**
	 * 生成随机数
	 *
	 * @return
	 */
//	public String generateCode() {
//		// 获取当前日期
//		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
//		String currentDate = dateFormat.format(new Date());
//
//		// 获取序列号
//		String ordersNumber = procuredPlanMapper.selectOrdersNumber();
//		String randomNumber;
//		// ...根据自己的业务逻辑实现获取序列号的方法
//		if (StringUtils.isEmpty(ordersNumber)) {
//			randomNumber = Constants.RANDOM_NUMBERS;
//		} else {
//			randomNumber = String.format("%04d", (NumberUtils.parseNumber(ordersNumber.substring(10), Long.class) + 1));
//		}
//
//		// 拼接生成的代码
//		String code = Constants.CODE_ORDERS + currentDate + randomNumber;
//
//		return code;
//	}

	/**
	 * 生成随机数
	 *
	 * @param
	 * @return
	 */
	private List<String> generateCode(Integer count) {
		synchronized (this) {  // 使用同步块，防止多线程并发访问
			// 获取当前日期
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
			String currentDate = dateFormat.format(new Date());

			// 获取最后一个收货单编号，在事务中加锁（使用 FOR UPDATE）
			String lastReceiptNumber = procuredPlanMapper.selectOrdersNumber();

			// 生成的编号列表
			List<String> generatedCodes = new ArrayList<>();

			// 如果没有找到最后一个编号，或者日期不匹配，说明是当天的第一个收货单
			String number;
			if (StringUtils.isEmpty(lastReceiptNumber) || !lastReceiptNumber.substring(2, 10).equals(currentDate)) {
				// 如果没有找到或者日期不匹配，生成从CR202411290001开始
				number = Constants.RANDOM_NUMBERS;
			} else {
				// 提取编号中的序列部分，并加一
				String lastNumberStr = lastReceiptNumber.substring(10); // 编号格式：CR + 日期（8位） + 序号（4位）
				long lastNumber = Long.parseLong(lastNumberStr);
				number = String.format("%04d", lastNumber + 1);
			}

			// 生成指定数量的编号
			for (int i = 0; i < count; i++) {
				String code = Constants.CODE_ORDERS + currentDate + number;
				// 检查生成的编号是否已存在，避免并发冲突
				int retryCount = 0;
				while (procuredPlanMapper.checkProcuredOrdersNumberExists(code) > 0 && retryCount < 5) {
					// 如果编号已经存在，重新生成
					retryCount++;
					String lastReceiptNumberRetry = procuredPlanMapper.selectOrdersNumber();
					if (StringUtils.isEmpty(lastReceiptNumberRetry) || !lastReceiptNumberRetry.substring(2, 10).equals(currentDate)) {
						number = Constants.RANDOM_NUMBERS;
					} else {
						String lastNumberStrRetry = lastReceiptNumberRetry.substring(10);
						long lastNumberRetry = Long.parseLong(lastNumberStrRetry);
						number = String.format("%04d", lastNumberRetry + 1);
					}
					code = Constants.CODE_ORDERS + currentDate + number;
				}

				if (retryCount >= 5) {
					// 达到重试次数限制，可以抛出异常或返回失败标志
					throw new RuntimeException("Failed to generate unique receipt number after 5 retries.");
				}

				// 将生成的编号添加到列表
				generatedCodes.add(code);

				// 更新编号的序号
				long currentNumber = Long.parseLong(number);
				number = String.format("%04d", currentNumber + 1);
			}

			return generatedCodes;
		}
	}

	/**
	 * 更新销售计划状态（判断是否全部已加入采购计划）
	 *
	 * @return
	 */
	private void updatePlanStatusByPlanId(Long planId, ProcuredPlan procuredPlan) {

		//汇总商品数量
		Wrapper<ShipmentsProduct> qw = Wrappers.lambdaQuery(ShipmentsProduct.class)
				.eq(ShipmentsProduct::getPlanId, planId)
				.eq(ShipmentsProduct::getDeleteStatus, "0");
		Long totalProductId = shipmentProductMapper.selectCount(qw);

		//汇总已选的商品数量
		Wrapper<ShipmentsProduct> qq = Wrappers.lambdaQuery(ShipmentsProduct.class)
				.eq(ShipmentsProduct::getPlanId, planId)
				.eq(ShipmentsProduct::getDeleteStatus, "0")
				.eq(ShipmentsProduct::getSelectStatus, "1");
		Long totalIsSelect = shipmentProductMapper.selectCount(qq);

		String selectStatus = "0";
		if (totalIsSelect >= totalProductId) {
			selectStatus = "1";
		}
		//更新销售计划表已选状态
		procuredPlanMapper.updatePlanStatusByPlanId(planId, selectStatus);
	}

	/**
	 * 更新销售计划明细表（tb_shipments_product）
	 *
	 * @return
	 */
	public void updateShipmentsProductSelectStatus(ProcuredPlan procuredPlan, Long salesPlanId) {
		// 查询该销售计划下所有销售计划明细（即所有产品）
		List<ShipmentsProduct> shipmentsProducts = shipmentProductMapper.selectByPlanId(salesPlanId);

		// 如果销售计划中没有任何产品，则直接返回（或根据业务需要做其它处理）
		if (CollectionUtils.isEmpty(shipmentsProducts)) {
			return;
		}

		// 获取销售计划中所有产品的ID
		List<Long> salesPlanProductIds = shipmentsProducts.stream()
				.map(ShipmentsProduct::getProductId)
				.collect(Collectors.toList());

		// 重新查询该销售计划下所有采购计划中的累计采购数量（不局限于当前采购计划）
		// 此处假设procuredProductMapper.selectByPlanId(productIds, salesPlanId)返回的是所有有效的采购计划中，
		// 销售计划中产品的采购记录（注意要排除已删除或无效的记录）
		// 修改分组逻辑，根据产品ID和GTIN分组
		Map<String, Integer> cumulativeProcuredMap = procuredProductMapper
				.selectByPlanId(salesPlanProductIds, salesPlanId)
				.stream()
				.collect(Collectors.groupingBy(
						p -> p.getProductId() + "-" + p.getGtin(),  // 使用产品ID和GTIN组合作为分组键
						Collectors.summingInt(ProcuredProduct::getNumber)
				));

		// --- 新增校验逻辑 --- //
		// 对于当前采购计划中的产品，校验其下单数量是否导致累计数量超过销售计划要求
		List<TbProcuredProduct> currentProducts = procuredPlan.getTbProcuredProductList();
		if (!CollectionUtils.isEmpty(currentProducts)) {
			for (TbProcuredProduct currentProduct : currentProducts) {
				// 找到对应的销售计划明细
				ShipmentsProduct sp = shipmentsProducts.stream()
						.filter(p -> p.getProductId().equals(currentProduct.getProductId()) && p.getGtin().equals(currentProduct.getGtin()))
						.findFirst().orElse(null);
				if (sp == null) {
					continue; // 没有找到对应的销售计划明细，根据实际情况可选择抛异常
				}
				int currentOrder = currentProduct.getNumber().intValue();
				// 累计采购数量包含当前采购计划的数量
				int cumulativeCount = cumulativeProcuredMap.getOrDefault(currentProduct.getProductId() + "-" + currentProduct.getGtin(), 0);
				// 其他采购计划中该产品的累计数量（即总累计数量减去当前采购计划中下单数量）
				int otherProcured = Math.max(0, cumulativeCount - currentOrder);
				// 剩余可采购数量 = 销售计划要求数量 - 其他采购计划中已下的数量
				int remaining = sp.getPlanSize().intValue() - otherProcured;
				if (currentOrder > remaining) {
					throw new ServiceException("产品 " + sp.getSku() + " 下单数量超出销售计划要求，剩余可采购数量为 " + remaining + " 个");
				}
			}
		}
		// --- 校验结束 --- //

		// 遍历所有销售计划明细进行更新
		for (ShipmentsProduct sp : shipmentsProducts) {
			// 计算累计采购数量，如果该产品在所有采购计划中没有下单，则为0
			int cumulativeCount = cumulativeProcuredMap.getOrDefault(sp.getProductId() + "-" + sp.getGtin(), 0);

			// 更新销售计划明细中的累计采购数量字段
			sp.setProcuredSelectedCount(cumulativeCount);

			// 判断是否“下完了”：只有累计数量正好等于销售计划中的计划数量时，认为该产品下完了
			String newSelectStatus = (cumulativeCount == sp.getPlanSize().intValue()) ? Constants.STATUS_ONE : Constants.CANCEL_STATUS_ZERO;
			sp.setSelectStatus(newSelectStatus);
			sp.setUpdateTime(new Date());

			// 执行数据库更新操作：更新选中状态（及必要时更新累计数量字段）
			procuredPlanMapper.updateShipmentsProductSelectStatus(sp.getProductId(), salesPlanId, newSelectStatus, new Date(), cumulativeCount,sp.getGtin());
		}
	}


//	/**
//	 * 比较采购计划商品的差异，新增还是删除
//	 *
//	 * @return
//	 */
//	public void compareProducts(ProcuredPlan procuredPlan, List<Long> longList) {
//
//		Long[] newProductIds = longList.toArray(new Long[0]);
//		Long[] oldProduceIds = procuredPlan.getShipmentsProductIds();
//
//		// 将数组转换为集合
//		Set<Long> newProductSet = new HashSet<>(Arrays.asList(newProductIds));
//		Set<Long> oldProduceSet = new HashSet<>(Arrays.asList(oldProduceIds));
//
//		// 找出 newProductIds 中不在 oldProduceIds 中的元素
//		Set<Long> newProductsNotInOld = new HashSet<>(newProductSet); // 创建副本
//		newProductsNotInOld.removeAll(oldProduceSet); // 从 newProductSet 中移除 oldProduceSet 中的所有元素
//
//		// 找出 oldProduceIds 中不在 newProductIds 中的元素
//		Set<Long> oldProductsNotInNew = new HashSet<>(oldProduceSet); // 创建副本
//		oldProductsNotInNew.removeAll(newProductSet); // 从 oldProduceSet 中移除 newProductSet 中的所有元素
//
//		//新增采购计划的商品
//		if (!newProductsNotInOld.isEmpty()) {
//			//更新销售计划明细表  selectStatus :0（未选），1（已选）
//			List<Long> productIdsList = new ArrayList<>(newProductsNotInOld);
//			if (!productIdsList.isEmpty()) {
//				procuredPlanMapper.updateShipmentsProductSelectStatusByProductIds(productIdsList, procuredPlan.getSalesPlanId(), "1", DateUtils.getNowDate());
//			}
//		}
//		//删除采购计划的商品
//		if (!oldProductsNotInNew.isEmpty()) {
//			//更新销售计划明细表
//			List<Long> productIdsList = new ArrayList<>(oldProductsNotInNew);
//			if (!productIdsList.isEmpty()) {
//				procuredPlanMapper.updateShipmentsProductSelectStatusByProductIds(productIdsList, procuredPlan.getSalesPlanId(), "0", DateUtils.getNowDate());
//			}
//		}
//
//		//更新销售计划状态（判断是否全部已加入采购计划）
//		updatePlanStatusByPlanId(procuredPlan.getSalesPlanId(), procuredPlan);
//	}

	/**
	 * 同步更新销售计划状态和销售计划商品明细
	 */
	/**
	 * 根据销售计划编号重新汇总该销售计划下所有剩余的采购计划中的采购产品，
	 * 然后调用 updateShipmentsProductSelectStatus 和 updatePlanStatusByPlanId 方法
	 * 重新更新销售计划明细的选中状态和整体销售计划状态。
	 */
	private void updatePlanAndShipmentsProductSelectStatus(String salesPlanNumber) {
		// 根据销售计划编号查询销售计划
		LambdaQueryWrapper<Plan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(Plan::getPlanNumber, salesPlanNumber);
		Plan plan = planMapper.selectOne(queryWrapper);
		if (plan == null || plan.getId() == null) {
			throw new RuntimeException("销售计划PlanId为空，请联系管理员核查。");
		}

		// 重新查询该销售计划下所有剩余采购计划中的采购产品
		List<TbProcuredProduct> aggregatedProducts = procuredPlanMapper.selectProcuredProductsBySalesPlanId(plan.getId());

		// 构造一个虚拟的ProcuredPlan，将所有采购产品汇总到一起，便于调用统一的更新方法
		ProcuredPlan aggregatedProcuredPlan = new ProcuredPlan();
		aggregatedProcuredPlan.setSalesPlanId(plan.getId());
		aggregatedProcuredPlan.setTbProcuredProductList(aggregatedProducts);

		// 根据新的采购产品汇总数据更新销售计划明细选中状态，
		// 该方法内部会将当前所有采购计划中对应产品的数量汇总，
		// 与销售计划中各产品的计划数量进行比较，从而决定是否更新为“已选”
		updateShipmentsProductSelectStatus(aggregatedProcuredPlan, plan.getId());

		// 更新销售计划整体状态（判断是否所有产品均已加入采购计划）
		updatePlanStatusByPlanId(plan.getId(), aggregatedProcuredPlan);
	}
	/**
	 * 修改采购计划下单状态
	 *
	 * @param planId
	 */
	public void updateProcuredPlanStatusByVersion(Long planId, BigDecimal payableAmount, Integer version) {
		boolean flag = true;//默认是已经下单完成
		//根据采购计划下的产品下单数量来修改采购计划的状态
		List<ProcuredProduct> procuredProductsList = procuredProductMapper.selectList(new LambdaQueryWrapper<>(ProcuredProduct.class)
				.eq(ProcuredProduct::getPlanId, planId));
		for (ProcuredProduct procuredProduct : procuredProductsList) {
			//如果已转数量要是小于总采购数量或者已转数量等于0都说明没有下单完成
			if (procuredProduct.getNumber() > procuredProduct.getTurnedNumber()) {
				flag = false;
			} else if (procuredProduct.getTurnedNumber() == 0) {
				flag = false;
			}
		}

		// 查询采购计划状态
		ProcuredPlan plan = procuredPlanMapper.selectById(planId);

		if (!Objects.equals(version, plan.getVersion())) {
			throw new ServiceException("数据发生变化，请刷新页面重试！");
		}

		int result = 0;
		//更新下单状态
		if (flag) {
			result = procuredPlanMapper.updatePlanStatus(planId, Constants.STATUS_THREE, payableAmount, plan.getVersion(), version);
		} else {
			result = procuredPlanMapper.updatePlanStatus(planId, Constants.STATUS_TOW, payableAmount, plan.getVersion(), version);
		}

		if (result == 0) {
			throw new ServiceException("数据发生变化，请刷新页面重试！");
		}
	}

	/**
	 * 修改采购商品表的已转数量和可转数量
	 *
	 * @param tbProcuredProducts
	 */
	private synchronized void updateProcuredProductNumber(List<TbProcuredProduct> tbProcuredProducts) {
		// 创建一个 Map，提前查询所有需要的 ProcuredProduct，减少数据库查询次数
		Map<Integer, ProcuredProduct> procuredProductMap = new HashMap<>();

		Set<Long> productIdSet = tbProcuredProducts.stream()
				.map(TbProcuredProduct::getId)
				.collect(Collectors.toSet());
		List<ProcuredProduct> procuredProducts = procuredProductMapper.selectBatchIds(productIdSet);
		for (ProcuredProduct procuredProduct : procuredProducts) {
			procuredProductMap.put(procuredProduct.getId(), procuredProduct);
		}


		// 修改采购商品表的已转数量和可转数量
		for (TbProcuredProduct ordersProduct : tbProcuredProducts) {
			Integer productId = ordersProduct.getId().intValue();
			ProcuredProduct procuredProduct = procuredProductMap.get(productId);


			if (procuredProduct != null) {
				// 如果版本号机制是一样的话，说明数据库中的数据还没有被别的用户更改
				if (!Objects.equals(ordersProduct.getVersion(), procuredProduct.getVersion())) {
					throw new ServiceException("数据发生变化，请刷新页面重试");
				}
				// 修改已转数量，增加本次下单的数量
//				procuredProduct.setTurnedNumber(procuredProduct.getTurnedNumber() + ordersProduct.getTransferableNumber().intValue());
				int turnedNumber = procuredProduct.getTurnedNumber() + ordersProduct.getTransferableNumber().intValue();

				// 修改可转数量 = 总数量 - 已转数量
//				procuredProduct.setTransferableNumber(procuredProduct.getNumber() - procuredProduct.getTurnedNumber());
				int transferableNumber = procuredProduct.getNumber() - turnedNumber;

				// 更新数据库
				LambdaUpdateWrapper<ProcuredProduct> updateWrapper = new LambdaUpdateWrapper<>();
				updateWrapper
						.set(ProcuredProduct::getTurnedNumber, turnedNumber)
						.set(ProcuredProduct::getTransferableNumber, transferableNumber)
						.set(ProcuredProduct::getVersion, procuredProduct.getVersion() + 1)
						.set(ProcuredProduct::getUpdateTime, new Date())
						.eq(ProcuredProduct::getVersion, ordersProduct.getVersion())
						.eq(ProcuredProduct::getId, procuredProduct.getId()); // 确保版本号一致
				int update = procuredProductMapper.update(procuredProduct, updateWrapper);
				if (update == 0) {
					throw new ServiceException("数据发生变化，请刷新页面重试！");
				}
			} else {
				throw new ServiceException("发生未知错误，请联系管理员");
			}
		}
	}

	/**
	 * 待我审核的采购计划
	 *
	 * @param procuredPlan
	 * @return 结果
	 */
	@Override
	public List<ProcuredPlan> getPlanWaitProcuredProcessList(ProcuredPlan procuredPlan) {
		return procuredPlanMapper.getPlanWaitProcuredProcessList(procuredPlan);
	}

	@Override
	public ProcuredPlan getPlanProducts(Long planId) {
		// 查询出采购计划
		ProcuredPlan planProducts = procuredProductMapper.getPlanProducts(planId);
		// 查询采购产品
//		List<ProcuredProduct> procuredProducts = procuredProductMapper.selectList(new LambdaQueryWrapper<ProcuredProduct>()
//				.eq(ProcuredProduct::getDeleteStatus, 0)
//				.eq(ProcuredProduct::getPlanId, planId));

		List<ProcuredProduct> procuredProducts = procuredProductMapper.selectListProcuredProduct(planId);

		List<TbProcuredProduct> tbProcuredProducts = new ArrayList<>();

		// 复制属性
		for (ProcuredProduct procuredProduct : procuredProducts) {
			TbProcuredProduct product = new TbProcuredProduct();
			BeanUtils.copyProperties(procuredProduct, product);
			product.setProductId(procuredProduct.getProductId().longValue());
			product.setNumber(procuredProduct.getNumber().longValue());
			product.setTurnedNumber(procuredProduct.getTurnedNumber().longValue());
			product.setTransferableNumber(procuredProduct.getTransferableNumber().longValue());
			product.setSku(procuredProduct.getSku());
			tbProcuredProducts.add(product);
		}
		if (!procuredProducts.isEmpty()) {
			// 提取出所有的产品id查询对应的图片
			Map<Integer, List<String>> collect = productImageMapper.selectProductImagesByProductId(procuredProducts.stream().map(item -> item.getProductId().longValue()).collect(Collectors.toList()))
					.stream().collect(Collectors.groupingBy(ProductImage::getProductId, Collectors.mapping(ProductImage::getProductImagePath, Collectors.toList())));
			// 分配产品图片
			for (TbProcuredProduct tbProcuredProduct : tbProcuredProducts) {
				tbProcuredProduct.setImgName(collect.get(tbProcuredProduct.getProductId().intValue()));
			}
		}
		planProducts.setTbProcuredProductList(tbProcuredProducts);
		return planProducts;
	}

	@Override
	public List<ProcuredPlanDto> selectProcuredByPlanId(String planNumber, Long productId) {
		List<ProcuredPlan> procuredPlans = procuredPlanMapper.selectByProductId(planNumber,productId);
		return procuredPlans.stream().map(
				item -> {
					ProcuredPlanDto dto = new ProcuredPlanDto();
					BeanUtils.copyProperties(item, dto);
					return dto;
				}
		).collect(Collectors.toList());
	}

	@Override
	public int updateTotal(Integer planId, int count) {
		return procuredPlanMapper.updateTotal(planId,count);
	}

	@Override
	public List<ProcuredPlanDto> selectProcuredPlan(String planNumber) {
		List<ProcuredPlan> procuredPlans = procuredPlanMapper.selectList(new LambdaQueryWrapper<ProcuredPlan>()
				.eq(ProcuredPlan::getSalesPlanNumber, planNumber)
				.eq(ProcuredPlan::getDeleteStatus, Constants.NOT_DELETED_STATUS));
		return procuredPlans.stream().map(
				item -> {
					ProcuredPlanDto dto = new ProcuredPlanDto();
					BeanUtils.copyProperties(item,dto);
					return dto;
				}
		).collect(Collectors.toList());
	}

	@Override
	public ProcuredPlanDto selectById(Long planId) {
		ProcuredPlan procuredPlan = procuredPlanMapper.selectById(planId);
		ProcuredPlanDto dto = new ProcuredPlanDto();
		BeanUtils.copyProperties(procuredPlan,dto);
		return dto;
	}

}
